<?php

namespace Melo\Config;

/**
 * Created by PhpStorm.
 * User: tusimo
 * Date: 10/28/19
 * Time: 7:12 PM
 */
class Config extends \Illuminate\Config\Repository
{
    private $configServer;

    private $appId;

    private $namespaces;

    private $clientIp;

    private $cluster;

    /**
     * Config constructor.
     * @param $configServer
     * @param $appId
     * @param $namespaces
     * @param $clientIp
     * @param $savePath
     * @throws \Exception
     */
    public function __construct($configServer, $appId, $namespaces, $savePath = null, $clientIp = null, $cluster = 'default')
    {
        parent::__construct();
        $this->setConfigServer($configServer);
        $this->setAppId($appId);
        $this->setNamespaces($namespaces);
        $this->setSavePath($savePath);
        $this->setClientIp($clientIp);
        $this->loadLocalConfig();
        $this->cluster = $cluster;
    }

    private $savePath;


    /**
     * 读取apollo配置
     * @param null $callback
     */
    public function run($callback = null)
    {
        if (is_null($callback)) {
            $callback = function () {
                echo "config changed sync config \r\n";
                $this->loadLocalConfig();
                reload_jobs();
            };
        } else {
            $callback = function () use ($callback) {
                $this->loadLocalConfig();
                $callback();
            };
        }
        $apollo = new ApolloClient($this->getConfigServer(), $this->getAppId(), $this->getNamespaces());

        if ($this->getClientIp()) {
            $apollo->setClientIp($this->getClientIp());
        }
        $cluster = $this->getCluster();
        $apollo->setCluster($cluster);
        $apollo->save_dir = $this->getSavePath();
        ini_set('memory_limit', '128M');
        $pid = getmypid();
        echo 'cluster is :' . $cluster . "\r\n";
        echo 'save_path is :' . $this->getSavePath() . "\r\n";
        echo 'config server is :' . $this->getConfigServer() . "\r\n";
        echo 'app_id is :' . $this->getAppId() . "\r\n";
        echo 'namespaces is :' . implode(',', $this->getNamespaces()) . "\r\n";
        echo "start [$pid]\r\n";
        $restart = true; //auto start if failed
        do {
            $error = $apollo->start($callback);
            if ($error) {
                echo('error:' . $error . "\r\n");
            } else {
                echo "get config success\r\n";
            }
            sleep(1);
            echo "restarting apollo config client daemon\r\n";
        } while ($restart);
    }

    public function loadLocalConfig()
    {
        $pattern = $this->getSavePath() . DIRECTORY_SEPARATOR . 'apolloConfig.*';
        $list = glob($pattern);
        foreach ($list as $l) {
            $config = require $l;
            if (is_array($config) && isset($config['configurations'])) {
                foreach ($config['configurations'] as $name => $value) {
                    if (is_json($value)) {
                        $value = json_decode($value, true);
                    }
                    data_set($this->items, $name, $value);
                }
            }
        }
        return $this->all();
    }

    public function merge($config)
    {
        $this->items = array_merge_recursive($config, $this->items);
    }

    /**
     * @return mixed
     */
    public function getClientIp()
    {
        return $this->clientIp;
    }

    /**
     * @param mixed $clientIp
     */
    public function setClientIp($clientIp)
    {
        $this->clientIp = $clientIp ? $clientIp : null;
    }

    /**
     * @return mixed
     */
    public function getNamespaces()
    {
        return $this->namespaces;
    }

    /**
     * @param mixed $namespaces
     */
    public function setNamespaces($namespaces)
    {
        !is_array($namespaces) && $namespaces = explode(',', $namespaces);
        $this->namespaces = $namespaces;
    }

    /**
     * @return mixed
     */
    public function getAppId()
    {
        return $this->appId;
    }

    /**
     * @param mixed $appId
     */
    public function setAppId($appId)
    {
        $this->appId = $appId;
    }

    /**
     * @return mixed
     */
    public function getConfigServer()
    {
        return $this->configServer;
    }

    /**
     * @param mixed $configServer
     */
    public function setConfigServer($configServer)
    {
        $this->configServer = $configServer;
    }

    /**
     * @return mixed
     */
    public function getSavePath()
    {
        return $this->savePath;
    }

    /**
     * @param mixed $savePath
     */
    public function setSavePath($savePath)
    {
        if (empty($savePath)) {
            $savePath = '/home/config/' . $this->getAppId();
        }
        if (!is_dir($savePath)) {
            @mkdir($savePath, 0777, true);
        }
        $this->savePath = $savePath;
    }

    public function getCluster()
    {
        $cluster = getenv('APOLLO_CLUSTER');
        if ($cluster !== false) {
            return $cluster;
        }
        return $this->cluster;
    }
}
